#include "Player.h"
#include <iostream>
#include <GL/glut.h>
#include <vector>
#include "Object3D.h"
#include "Projectile.h"
#include "Vector3.h"
#include <cmath>

using namespace std;


int lastState = 0;
bool facingRight = true;
bool inAir = false;

float degrees = 0;

const int Player::HURT_DELAY = 100;

void Player::onAnimationFinish(int state)
{
	if (dying)
	{
		cout << "DEAD = TRUE" << endl;
		dead = true;
		xVel = yVel = 0;
		dying = true;
		
		canDraw = true;
		lastHurtTime = HURT_DELAY;
	}else{
		mModel->SetState(lastState, true);
	}
}

Player::Player() : moveSpeed(20), health(500), lastHurtTime(0), canDraw(true)
{
	type = PLAYER;
	cw = 15;
	ch = 25;
	offsetX = -50;
	mModel = new Object3D(2, this);
	
	
	//if (mModel->LoadModel("Models/Ogro/Ogros.md2","Models/Ogro/Ogro.pcx") &&
	//	mModel->LoadModel("Models/Ogro/Weapon.md2","Models/Ogro/Weapon.pcx") )
	if (mModel->LoadModel("Models/martian/TRIS.MD2","Models/martian/MARTIAN.pcx") &&
		mModel->LoadModel("Models/martian/Weapon.MD2","Models/martian/Weapon.pcx") )
	
	{
	}else
	{
		std::cout << "error loading model" << std::endl;
	}

	/*
	BMPClass bmp;
	BMPLoad("big_glow.bmp",bmp);
	
	glGenTextures(1, &glowTex);
	glBindTexture(GL_TEXTURE_2D, glowTex);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 
	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 
	
	glTexImage2D(GL_TEXTURE_2D,0,3,bmp.width,bmp.height,0,GL_RGB,GL_UNSIGNED_BYTE,bmp.bytes);
	*/
}

Player::~Player()
{
	// Delete fired projectiles
	for (vector<Projectile*>::iterator it = projectiles.begin(); it != projectiles.end(); it++)
	{
		delete (*it);
	}
	delete mModel;
}

void Player::handleKey(int key, bool down)
{
	if (dying)
		return;
	if (down)
	{
		switch (key)
		{
		case GLUT_KEY_LEFT:
			xVel -= moveSpeed;
		
			facingRight = false;
			offsetX = 50;
			mModel->SetState(kRunning,true);
			break;
		case GLUT_KEY_RIGHT:
			xVel += moveSpeed;
			
			facingRight = true;
			offsetX = -50;
			mModel->SetState(kRunning,true);
			break;
		case 32:
			if (!inAir)
			{
				yVel += 30;//5;
				//mModel->SetState(kJumping);
			}
			break;
		case 's':
			//glShadeModel(GL_FLAT);
			//position.x = 0;
			//position.y = 0;
			break;
		case 'a':
			// ATTACK
			
			if ( mModel->repeat )
				lastState = mModel->GetCurrentState();
			mModel->SetState(kShotShoulder,false);
			Projectile* p = new Projectile();
			p->setPosition(position.x, position.y + 70, 0);
			if (facingRight)
			{
				p->xVel = 50;
			}else{
				p->xVel = -50;
			}
			projectiles.push_back(p);
			
			break;
		}
	}else
	{
		switch (key)
		{
		case GLUT_KEY_LEFT:
			mModel->SetState(kIdle1,true);
			if (xVel < 0) // !=

					xVel += moveSpeed;
				
			break;
		case GLUT_KEY_RIGHT:
			mModel->SetState(kIdle1,true);
			if (xVel > 0) // !=
	
					xVel -= moveSpeed;
				
			break;
		case 32:
			
			break;
		}
	}
	
}

void Player::move(const std::vector<Collidable*>& plats)
{
	// Move fired projectiles
	for (vector<Projectile*>::iterator it = projectiles.begin(); it != projectiles.end();)
	{
		if ( (*it)->dead )
		{
			delete (*it);
			it = projectiles.erase(it);
		}else{
			(*it)->move(plats);
			it++;
		}
	}

	if (dead)
		return;

	if (health <= 0)
		youreDead();

	if (lastHurtTime < HURT_DELAY && !dying)
	{
		// Blink?
		if ( (lastHurtTime % 10) == 0 )
		{
			canDraw = !canDraw;
		}
		lastHurtTime++;
	}else{
		canDraw = true;
	}
	

	position.x += xVel;
	
	Collidable* collision = checkCollision(plats);
	if (collision){

			position.x -= xVel;
			xVel = 0;

	}


	yVel -= 0.6;//0.2;			// gravity
	position.y += yVel;
	collision = checkCollision(plats);
	if (collision){

		if (yVel < 0)		// Fell to ground
		{
			inAir = false;
		}
			
		position.y -= yVel;
		yVel = 0;
	}else{
		inAir = true;
	}

	//if (!inAir)
	if ( !inAir || !mModel->repeat )
	{
		mModel->Update();
	}
	
}

void Player::draw()
{
	

	if (canDraw)
	{
		//GLfloat diff[4] = {0,1,1,1};
		GLfloat spec[4] = {1,1,1,1};

		int shininess = 128;
		//glMaterialfv(GL_FRONT,GL_DIFFUSE, diff);
		glMaterialfv(GL_FRONT,GL_SPECULAR, spec);

		glMateriali(GL_FRONT,GL_SHININESS, shininess);


		glEnable(GL_TEXTURE_2D);
		//glDisable(GL_TEXTURE_2D);
		glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); 

		glMatrixMode(GL_MODELVIEW);
		glPushMatrix();

		glTranslatef(position.x + offsetX, position.y + offsetY, 0);

		glScalef(sx,sy,sz);

		//glutSolidCube(ch * 2);

		if (!facingRight)
		{
			glRotatef(-180,0,1,0);
		}
		glRotatef(-90,1,0,0);

		mModel->Draw();

		glPopMatrix();

		glDisable(GL_TEXTURE_2D);
	}


	// Draw fired projectiles
	for (vector<Projectile*>::iterator it = projectiles.begin(); it != projectiles.end(); it++)
	{
		(*it)->draw();
	}
	
}

// OVERRIDE!
Collidable* Player::checkCollision(const std::vector<Collidable*>& plats)
{
	float scaledW = sx * cw;
	float scaledH = sy * ch;
	float leftA = position.x - scaledW;
	float topA = position.y + scaledH;
	float rightA = position.x + scaledW;
	float bottomA = position.y - scaledH;

	for (std::vector<Collidable*>::const_iterator it = plats.begin(); it != plats.end(); it++)
	{
		
		float sxB = (*it)->sx;
		float syB = (*it)->sy;
		float leftB = (*it)->position.x - ( ((*it)->cw) * sxB );
		float topB = (*it)->position.y + ( ((*it)->ch) * syB );
		float rightB = (*it)->position.x + ( ((*it)->cw) * sxB );
		float bottomB = (*it)->position.y - ( ((*it)->ch) * syB );
	
		if ( (leftA < rightB) && (rightA > leftB) && (topA > bottomB) && (bottomA < topB) )
		{
			if ( (*it)->type == ENEMY )
			{
				if (lastHurtTime >= HURT_DELAY && !(*it)->dying)
				{
					health -= 100;
					lastHurtTime = 0;
				}
				continue;
			}
			return (*it);
		}
	}
	return 0;
}

void Player::youreDead()
{
	dying = true;
	mModel->SetState(kFallingBackSlowDying,false);
	
}